JBoss Community Archive (Read Only)

Infinispan 5.1

CDI Support

Introduction

Infinispan includes integration with CDI in the infinispan-cdi module. Configuration and injection of the Inifispan's Cache API is provided, and it is planned to bridge Cache listeners to the CDI event system. The module also provide partial support of the JCache (JSR-107) caching annotations - for further details see Chapter 8 of the JCACHE specification.

Maven Dependencies

All you need is org.infinispan:infinispan-cdi

<dependency>
    <groupId>org.infinispan</groupId>
    <artifactId>infinispan-cdi</artifactId>
    <version>${infinispan.version}</version>
</dependency>
Which version of Infinispan should I use?

We recommend using the latest final version of the infinispan-cdi module. This module is available since Infinispan version 5.0.0.CR8.

Embedded cache integration

Inject an embedded cache

By default you can inject the default Infinispan cache. Let's look at the following example:

...
import javax.inject.Inject;

public class GreetingService {
    @Inject
    private Cache<String, String> cache;

    public String greet(String user) {
        String cachedValue = cache.get(user);
        if (cachedValue == null) {
            cachedValue = "Hello " + user;
            cache.put(user, cachedValue);
        }
        return cachedValue;
    }
}

If you want to use a specific cache you just have to provide your own cache configuration and cache qualifier. For example, if you want to use a custom cache for the GreetingService you should write your own qualifier (here GreetingCache) and define its configuration:

The new configuration system is used since 5.1.0.CR2

As you probably know Infinispan 5.1.0 comes with a new way to configure your cache programmatically and a bit more (more information are available here). Now to configure a cache you must use this new configuration system.

...
import javax.inject.Qualifier;

@Qualifier
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GreetingCache {
}
...
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.cdi.ConfigureCache;
import javax.enterprise.inject.Produces;

public class Config {
    @ConfigureCache("greeting-cache") // This is the cache name.
    @GreetingCache // This is the cache qualifier.
    @Produces
    public Configuration greetingCacheConfiguration() {
        return new ConfigurationBuilder()
                    .eviction()
                        .strategy(EvictionStrategy.FIFO)
                        .maxEntries(4)
                    .build();
    }

    // The same example without providing a custom configuration.
    // In this case the default cache configuration will be used.
    @ConfigureCache("greeting-cache")
    @GreetingCache
    @Produces
    public Configuration greetingCacheConfiguration;
}

To use this cache in the GreetingService add the @GeetingCache qualifier on your cache injection point. Simple!

Override the default embedded cache manager and configuration

Since 5.1.0.CR1 @OverrideDefault is deprecated

To migrate your code remove this annotation from your producers as detailed in the following section.

You can override the default cache configuration used by the default embedded cache manager. For that, you just have to create one Configuration producer with the @Default qualifier as illustrated in the following snippet:

public class Config {
    // By default CDI adds the @Default qualifier if no other qualifier is provided.
    @Produces
    public Configuration defaultEmbeddedCacheConfiguration() {
        return new ConfigurationBuilder()
                    .eviction()
                        .strategy(EvictionStrategy.FIFO)
                        .maxEntries(4)
                    .build();
    }
}

It's also possible to override the default embedded cache manager used. The new default cache manager produced must have the @Default qualifier and the scope @ApplicationScoped.

...
import javax.enterprise.context.ApplicationScoped;

public class Config {
    @Produces
    @ApplicationScoped
    public EmbeddedCacheManager defaultEmbeddedCacheManager() {
      return new DefaultCacheManager(new ConfigurationBuilder()
                                          .eviction()
                                              .strategy(EvictionStrategy.FIFO)
                                              .maxEntries(4)
                                          .build());
   }
}

Configure the transport for clustered use

To use Infinispan in a clustered mode you have to configure the transport with the GlobalConfiguration. To achieve that override the default cache manager as explained in the previous section. Look at the following snippet:

...
package org.infinispan.configuration.global.GlobalConfigurationBuilder;

@Produces
@ApplicationScoped
public EmbeddedCacheManager defaultClusteredCacheManager() {
    return new DefaultCacheManager(
        new GlobalConfigurationBuilder().transport().defaultTransport().build(),
        new ConfigurationBuilder().eviction().maxEntries(7).build()
    );
}

Remote cache integration

Inject a remote cache

With the CDI integration it's also possible to use a remote cache. For example you can inject the default RemoteCache as illustrated in the following snippet:

public class GreetingService {
    @Inject
    private RemoteCache<String, String> cache;

    public String greet(String user) {
        String cachedValue = cache.get(user);
        if (cachedValue == null) {
            cachedValue = "Hello " + user;
            cache.put(user, cachedValue);
        }
        return cachedValue;
    }
}

If you want to use another cache, for example the greeting-cache, add the @Remote qualifier on the cache injection point which contains the cache name.

public class GreetingService {
    @Inject @Remote("greeting-cache")
    private RemoteCache<String, String> cache;

    ...
}

Adding the @Remote cache qualifier on each injection point might be error prone. That's why the remote cache integration provides another way to achieve the same goal. For that you have to create your own qualifier annotated with @Remote:

@Remote("greeting-cache")
@Qualifier
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RemoteGreetingCache {
}

To use this cache in the GreetingService add the qualifier @RemoteGreetingCache qualifier on your cache injection.

Override the default remote cache manager

Like the embedded cache integration, the remote cache integration comes with a default remote cache manager producer. This default remote cache manager can be overridden as illustrated in the following snippet:

public class Config {
    @Produces
    @ApplicationScoped
    public RemoteCacheManager defaultRemoteCacheManager() {
        return new RemoteCacheManager(localhost, 1544);
    }
}

Use a custom remote/embedded cache manager for one or more cache

It's possible to use a custom cache manager for one or more cache. You just need to annotate the cache manager producer with the cache qualifiers. Look at the following example:

public class Config {
   @GreetingCache
   @Produces
   @ApplicationScoped
   public EmbeddedCacheManager specificEmbeddedCacheManager() {
      return new DefaultCacheManager(new ConfigurationBuilder()
                                          .expiration()
                                              .lifespan(60000l)
                                          .build());
   }

   @RemoteGreetingCache
   @Produces
   @ApplicationScoped
   public RemoteCacheManager specificRemoteCacheManager() {
       return new RemoteCacheManager("localhost", 1544);
   }
}

With the above code the GreetingCache or the RemoteGreetingCache will be associated with the produced cache manager.

Producer method scope

To work properly the producers must have the scope @ApplicationScoped. Otherwise each injection of cache will be associated to a new instance of cache manager.

Use a JBoss AS 7 configured cache

With JBoss AS 7, you can setup an Infinispan cache manager in the server configuration file. This allows you to externalize your Infinispan configuration and also to lookup the cache manager from JNDI, normally with the @Resource annotation.

As we mentioned earlier, you can override the default cache manager used by the Infinispan CDI extension. To use a JBoss AS 7 configured cache, you need to use the cache manager defined in JBoss AS 7. You only need to annotate the default cache manager producer with @Resource. The following example shows how use an embedded cache manager configured in JBoss AS 7.

...
import javax.annotation.Resource;

public class Config {
    @Produces
    @ApplicationScoped
    @Resource(lookup="java:jboss/infinispan/my-container-name")
    private EmbeddedCacheManager defaultCacheManager;
}

Use JCache caching annotations

The infinispan-cdi module provides a partial support of JCache caching annotations. These annotations provide a simple way to handle common use cases. The following caching annotations are defined in this specification:

  • @CacheResult caches the result of a method call

  • @CachePut caches a method parameter

  • @CacheRemoveEntry removes an entry from a cache

  • @CacheRemoveAll removes all entries from a cache

Annotations target type

These annotations must only be used on methods.

To use these annotations the following interceptors must be declared in your application beans.xml.

<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
    <interceptors>
        <class>org.infinispan.cdi.interceptor.CacheResultInterceptor</class>
        <class>org.infinispan.cdi.interceptor.CachePutInterceptor</class>
        <class>org.infinispan.cdi.interceptor.CacheRemoveEntryInterceptor</class>
        <class>org.infinispan.cdi.interceptor.CacheRemoveAllInterceptor</class>
    </interceptors>
</beans>

The following snippet of code illustrates the use of @CacheResult annotation. As you can see it simplifies the caching of the Greetingservice#greet method results.

import javax.cache.interceptor.CacheResult;

public class GreetingService {
    @CacheResult
    public String greet(String user) {
        return "Hello" + user;
    }
}

The first version of the GreetingService and the above version have exactly the same behavior. The only difference is the cache used. By default it's the fully qualified name of the annotated method with its parameter types (e.g. org.infinispan.example.GreetingService.greet(java.lang.String)).

Can I use a different cache?

To use another cache specify its name with the cacheName attribute of the cache annotation. For example:

@CacheResult(cacheName = "greeting-cache")
JBoss.org Content Archive (Read Only), exported from JBoss Community Documentation Editor at 2020-03-11 09:17:01 UTC, last content change 2012-01-16 11:33:22 UTC.